Invalid transactions [Sliding Window, Line Sweep]

Time: O(NLogN); Space: O(N); medium

A transaction is possibly invalid if: * the amount exceeds $1000, or; * if it occurs within (and including) 60 minutes of another transaction with the same name in a different city.

Each transaction string transactions[i] consists of comma separated values representing the name, time (in minutes), amount, and city of the transaction.

Given a list of transactions, return a list of transactions that are possibly invalid. You may return the answer in any order.

Example 1:

Input: transactions =

["alice, 20, 800, mtv",
 "alice, 50, 100, beijing"
]

Output:

["alice, 20, 800, mtv",
 "alice, 50, 100, beijing"]

Explanation:

  • The first transaction is invalid because the second transaction occurs within a difference of 60 minutes, have the same name and is in a different city.

  • Similarly the second one is invalid too.

Example 2:

Input: transactions =

["alice, 20, 800, mtv",
 "alice, 50, 1200, mtv"]

Output:

["alice, 50, 1200, mtv"]

Example 3:

Input: transactions =

["alice, 20, 800, mtv",
 "bob, 50, 1200, mtv"]

Output:

["bob, 50, 1200, mtv"]

Notes:

  • len(transactions) <= 1000

  • Each transactions[i] takes the form “{name},{time},{amount},{city}”

  • Each {name} and {city} consist of lowercase English letters, and have lengths between 1 and 10.

  • Each {time} consist of digits, and represent an integer between 0 and 1000.

  • Each {amount} consist of digits, and represent an integer between 0 and 2000.

[5]:
import collections

class Solution1(object):
    def invalidTransactions(self, transactions):
        AMOUNT, MINUTES = 1000, 60

        trans = list(map(lambda x: (x[0], int(x[1]), int(x[2]), x[3]),
                    (transaction.split(',') for transaction in transactions)))
        trans.sort(key=lambda t: t[1])
        trans_indexes = collections.defaultdict(list)

        for i, t in enumerate(trans):
            trans_indexes[t[0]].append(i)

        result = []
        for name, indexes in trans_indexes.items():
            left, right = 0, 0
            for i, t_index in enumerate(indexes):
                t = trans[t_index]
                if (t[2] > AMOUNT):
                    result.append("{},{},{},{}".format(*t))
                    continue

                while left+1 < len(indexes) and trans[indexes[left]][1] < t[1]-MINUTES:
                    left += 1

                while right+1 < len(indexes) and trans[indexes[right+1]][1] <= t[1]+MINUTES:
                    right += 1

                for i in range(left, right+1):
                    if trans[indexes[i]][3] != t[3]:
                        result.append("{},{},{},{}".format(*t))
                        break
        return result
[11]:
s = Solution1()
transactions = ["alice, 20, 800, mtv", "alice, 50, 100, beijing"]
assert s.invalidTransactions(transactions) == ['alice,20,800, mtv', 'alice,50,100, beijing']
transactions = ["alice, 20, 800, mtv", "alice, 50, 1200, mtv"]
assert s.invalidTransactions(transactions) == ['alice,50,1200, mtv']
transactions = ["alice, 20, 800, mtv", "bob, 50, 1200, mtv"]
assert s.invalidTransactions(transactions) == ['bob,50,1200, mtv']